// Object, {}, 和 object 的区别
type NoObj = Record<never, never>;
{
  // Object 可以作为对象类型 可以表示 除 undefined 的任何值。
  // 最大区别
  // # 在使用时，类型为 Object 的变量 在提示时只能访问到 Object 接口 上的方法
  let a: Object = {}; // valid, because {} is an object
  let b: Object = []; // valid, because [] is an array, which is an object
  let c: Object = 42; // invalid, because 42 is a number, a primitive type
  let d: Object = 'hello'; // invalid, because "hello" is a string, a primitive type
  let e: Object = new Number(1); // valid, because new Number(1) is an object
  // @ts-expect-error
  let f: Object = null;
  // @ts-expect-error
  let g: Object = undefined; // invalid
  g.constructor;
  //   ^?
  type _ = keyof typeof g;
}
{
  Object.create(null); // should be {}
  // {} 表示空对象类型，也可表示未定义特定属性的对象。也可以用 `Record<never, never>` 表示{
  // # {} 是所有对象类型的父类型，它也可以表示任何非空类型的值(最抽象的对象)
  // # 在使用时，object 有提示任何属性提示，因为表示没有属性
  let t: {} = []; // valid:
  let x: {} = {} as Record<never, never>; // valid
  let y: {} = 42; // valid, although 42 is a number, `{}` allows any type
  let z: {} = 'hello'; // valid, although "hello" is a string, `{}` allows any type
  let e: {} = new Number(1);
  let h: {} = { a: 1 };
  // @ts-expect-error
  let w: {} = null; // invalid
  // @ts-expect-error
  let v: {} = undefined; // invalid
  v.constructor;
  //   ^?
  type _ = keyof typeof v;
}
{
  // object 表示任何非原始类型 的对象。
  let p: object = {}; // valid
  let q: object = []; // valid
  // @ts-expect-error
  let r: object = 42; // invalid, because 42 is a number
  // @ts-expect-error
  let s: object = 'hello'; // invalid, because "hello" is a string
  // @ts-expect-error
  let t: object = null; // invalid, because null is a primitive type
  // @ts-expect-error
  let u: object = undefined; // invalid, because undefined is a primitive type
}
// https://juejin.cn/post/7108617813560197127
// @ts-expect-error
// 一个例子，出现原因是 Object 类型 显示包含了 Object 的原型方法 (很少用到),
//  而这里发生了隐式重载，导致类型不匹配的报错
const a: Object = {} as { toString(): number };
//> 总结：
// 三种类型中，常用排序的有 object, {}(间接使用), Object
// object 只表示引用对象，作为对象类型的占位符使用
// {} 表示 非空的任意类型 同 NonNullable<unknown>, 也可用 Record<never, never> 表示
// Object 不常用，可能是因为 要打的字多 或者 Object 原型属性 字段干扰，
//  实际上除了 Object 原型方法是显示提示的 (与 {}比较) 之外，与 {} 没什么区别
